package proto

import (
	"github.com/golang/protobuf/proto"
)

type Filter_FieldEventMode int32

const (
	Filter_ERR_ON_MISMATCH Filter_FieldEventMode = 0
	Filter_BEST_EFFORT     Filter_FieldEventMode = 1
)

type OnDDLAction int32

const (
	OnDDLAction_IGNORE      OnDDLAction = 0
	OnDDLAction_STOP        OnDDLAction = 1
	OnDDLAction_EXEC        OnDDLAction = 2
	OnDDLAction_EXEC_IGNORE OnDDLAction = 3
)

var OnDDLAction_name = map[int32]string{
	0: "IGNORE",
	1: "STOP",
	2: "EXEC",
	3: "EXEC_IGNORE",
}

var OnDDLAction_value = map[string]int32{
	"IGNORE":      0,
	"STOP":        1,
	"EXEC":        2,
	"EXEC_IGNORE": 3,
}

func (x OnDDLAction) String() string {
	return proto.EnumName(OnDDLAction_name, int32(x))
}

type Filter struct {
	Rules []*Rule
}

type RuleType uint8

const (
	RuleTypeTable RuleType = iota
	RuleTypeTables
	RuleTypeRegexp
)

type Rule struct {
	Dbname       string
	Type         RuleType
	Table        string
	Tables       map[string]struct{}
	Regexp       string
	Filter       string
	TargetDbname string
}

type VEventType int32

const (
	VEventType_UNKNOWN  VEventType = 0
	VEventType_GTID     VEventType = 1
	VEventType_BEGIN    VEventType = 2
	VEventType_COMMIT   VEventType = 3
	VEventType_ROLLBACK VEventType = 4
	VEventType_DDL      VEventType = 5
	// INSERT, REPLACE, UPDATE, DELETE and SET will not be seen in RBR mode.
	VEventType_INSERT  VEventType = 6
	VEventType_REPLACE VEventType = 7
	VEventType_UPDATE  VEventType = 8
	VEventType_DELETE  VEventType = 9
	VEventType_SET     VEventType = 10
	// OTHER is a dummy event. If encountered, the current GTID must be
	// recorded by the client to be able to resume.
	VEventType_OTHER VEventType = 11
	VEventType_ROW   VEventType = 12
	VEventType_FIELD VEventType = 13
	// HEARTBEAT is sent if there is inactivity. If a client does not
	// receive events beyond the hearbeat interval, it can assume that it's
	// lost connection to the vstreamer.
	VEventType_HEARTBEAT VEventType = 14
	// VGTID is generated by VTGate's VStream that combines multiple
	// GTIDs.
	VEventType_VGTID     VEventType = 15
	VEventType_JOURNAL   VEventType = 16
	VEventType_VERSION   VEventType = 17
	VEventType_LASTPK    VEventType = 18
	VEventType_SAVEPOINT VEventType = 19
	VEventType_RAW_GTID  VEventType = 20
)

type IPosition interface {
	String() string
}

type IGTID interface {
	String() string
}

type VEvent struct {
	Type VEventType
	// Timestamp is the binlog timestamp in seconds.
	// The value should be ignored if 0.
	Timestamp int64
	// Gtid is set if the event type is GTID.
	Gtid IPosition
	// Statement is set if the event type is DDL, DML or SAVEPOINT.
	Statement    string
	Dbname       string
	TargetDbname string
	TableName    string // todo Currently only used in ddl such as Alter
	// RowEvent is set if the event type is ROW.
	RowEvent *RowEvent
	// FieldEvent is set if the event type is FIELD.
	FieldEvent *FieldEvent
	// Dml is set if the event type is INSERT, REPLACE, UPDATE or DELETE.
	Dml string
	// CurrentTime specifies the current time when the message was sent.
	// This can be used to compenssate for clock skew.
	CurrentTime int64
	// LastPK is the last PK for a table
	LastPKEvent *LastPKEvent
}

type FieldEvent struct {
	Dbname    string
	TableName string
	Fields    []*Field
}

type RowEvent struct {
	Dbname     string
	TableName  string
	Gtid       IGTID
	RowChanges []*RowChange
}

type RowChange struct {
	Before  *Row
	After   *Row
	PkValue []byte
}

type LastPKEvent struct {
	TableLastPK *TableLastPK
	Completed   bool
}

type TableLastPK struct {
	TableName string
	Lastpk    *QueryResult
}

type VStreamRowsResponse struct {
	Fields   []*Field
	Pkfields []*Field
	Gtid     string
	Rows     []*Row
	Lastpk   *Row
}

// Charset is the per-statement charset info from a QUERY_EVENT binlog entry.
type Charset struct {
	// @@session.character_set_client
	Client int32
	// @@session.collation_connection
	Conn int32
	// @@session.collation_server
	Server int32
}
